package com.clms.system.myconfig;

import com.clms.common.JwtUtils;
import com.clms.common.util.Payload;
import com.clms.system.mapper.SysOperLogMapper;
import com.clms.system.pojo.entitry.SysOperLog;
import com.clms.system.pojo.entitry.SysUser;
import com.clms.system.pojo.util.WebUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import sun.net.util.IPAddressUtil;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;

/**
 * @program: clms-third
 * @description:
 * @author: 大鱼
 * @create: 2021-07-25 20:19
 **/

@Slf4j
//@Aspect
//@Component
public class LogAop  {
    @Autowired
    private SysOperLogMapper sysLogMapper;
    //开始时间
    private Long visitTime;
     //访问类
    private Class clazz;
    //访问方法
    private Method method;
    @Autowired
    private SysOperLog operLog;
    @Autowired
    RsaKeyProperties properties;
    //切点
//    @Pointcut("execution(* com.clms.system.controller.*.*(..))")
    @Pointcut("@annotation(com.clms.system.myconfig.LogAnnotation)")
    private void aspect() { }
    @Before("aspect()")
    public void before(JoinPoint joinpoint) throws NoSuchMethodException {

        saveLog(joinpoint);
    }
    public void saveLog(JoinPoint joinpoint) throws NoSuchMethodException {
        visitTime = System.currentTimeMillis();
        Date date = new Date(visitTime);

        clazz = joinpoint.getTarget().getClass();
        String methodName = joinpoint.getSignature().getName();
        Object[] args = joinpoint.getArgs();
        if (args == null || args.length == 0) { //获取方法名
            method = clazz.getMethod(methodName);
        } else {
            Class[] argsClass = new Class[args.length];
            for (int i = 0; i < args.length; i++) {
                argsClass[i] = args[i].getClass();
            }
            method = clazz.getMethod(methodName, argsClass);
        }

        HttpServletRequest request = WebUtil.getRequest();

        String requestMethod = request.getMethod();
        String nowtime=new SimpleDateFormat("yyyy-mm-dd hh:mm:ss").format(date);
        operLog.setOperTime(nowtime);//设置时间
        operLog.setOperIp(request.getRemoteAddr());//设置IP
        operLog.setOperUrl(request.getRequestURI());//设置映射路径
        operLog.setOperatorType(request.getMethod());//请求方式
        operLog.setOperParam( Arrays.toString(joinpoint.getArgs()));//请求参数
        String token = request.getHeader("token");//解析用户信息
        if (StringUtils.isNotEmpty(token)) {

        Payload<SysUser> info = JwtUtils.getInfoFromToken(token,properties.getPublicKey(), SysUser.class);
            operLog.setOperId(info.getUserInfo().getUserId());
            operLog.setOperName(info.getUserInfo().getUserName());
        }
        operLog.setMethod(String.valueOf(clazz.getMethod(methodName)));
        String url = "";
      /*  if (clazz != null && method != null) {
            RequestMapping clazzAnnotation = (RequestMapping) clazz.getAnnotation(RequestMapping.class);
            if (clazzAnnotation != null) {
                String[] classValue = clazzAnnotation.value();
                if ("Get".equals(requestMethod)) {
                    GetMapping methodAnotation = method.getAnnotation(GetMapping.class);
                    if (methodAnotation != null) {
                        String[] methodValue = methodAnotation.value();
                        url = classValue[0] + methodValue[0];
                        log.info("url:{}", url);

                    } else {
                        PostMapping methodAnnotation = method.getAnnotation(PostMapping.class);
                        if (methodAnnotation != null) {
                            String[] methodValue = methodAnotation.value();
                            url = classValue[0] + methodValue[0];
                            log.info("url:{}", url);
                        }
                        log.info("类名{}方法名{}", clazz.getName(),method.getName(),methodName);
                    }
                }
            }
            log.info("请求结束--------------------------");
        }*/
        MethodSignature signature = (MethodSignature) joinpoint.getSignature();
        Method method = signature.getMethod();


        LogAnnotation logAnnotation = method.getAnnotation(LogAnnotation.class);
        if (logAnnotation != null) {
      operLog.setTitle(logAnnotation.title());
        }

        if (internalIp(request.getRemoteAddr())) {
            operLog.setOperLocation("内网Ip");
        } else {
            operLog.setOperLocation("外网Ip");
        }


        sysLogMapper.insert(operLog);
    }

    public static boolean internalIp(String ip) {
        byte[] addr = IPAddressUtil.textToNumericFormatV4(ip);
        return internalIp(addr);
    }


    public static boolean internalIp(byte[] addr) {
        final byte b0 = addr[0];
        final byte b1 = addr[1];
        //10.x.x.x/8
        final byte SECTION_1 = 0x0A;
        //172.16.x.x/12
        final byte SECTION_2 = (byte) 0xAC;
        final byte SECTION_3 = (byte) 0x10;
        final byte SECTION_4 = (byte) 0x1F;
        //192.168.x.x/16
        final byte SECTION_5 = (byte) 0xC0;
        final byte SECTION_6 = (byte) 0xA8;
        switch (b0) {
            case SECTION_1:
                return true;
            case SECTION_2:
                if (b1 >= SECTION_3 && b1 <= SECTION_4) {
                    return true;
                }
            case SECTION_5:
                switch (b1) {
                    case SECTION_6:
                        return true;
                }
            default:
                return false;

        }
    }

/*在方法执行完结后打印返回内容
@param obj 返回值
* */
 /*   @AfterReturning(returning = "obj",pointcut = "aspect()")
    public void methodAfterReturturning(Object obj) {
        Long time = System.currentTimeMillis();
        log.info("执行时长：{}s", time / 1000);
        log.info("--------------------------------------返回内容");

        try {
            log.info(mapper.writeValueAsString(obj));
        } catch (JsonProcessingException e) {
            e.printStackTrace();
            log.error("发生错误",e);
        }
        log.info("返回内容=======================");
    }*/
}
